﻿using Ewk.Math.ComputationTypes;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Ewk.Math.Algebra.UnitTests.MatrixTests.NullTests
{
    [TestClass]
    public class MatrixNullUnitTests : MatrixUnitTestsBase<double>
    {
        #region Static Add
        [TestMethod]
        public void Matrix_static_Add_with_a_null_Matrix_and_a_null_Matrix_gives_null()
        {
            var result = Matrix<double>.Add(null, (Matrix<double>)null);

            Assert.IsNull(result);
        }

        [TestMethod]
        public void Matrix_static_Add_with_a_null_Matrix_and_a_null_Computable_gives_null()
        {
            var result = Matrix<double>.Add(null, (Computable<double>)null);

            Assert.IsNull(result);
        }

        [TestMethod]
        public void Matrix_static_Add_with_a_null_Matrix_and_a_Computable_gives_null()
        {
            var result = Matrix<double>.Add(null, 0);

            Assert.IsNull(result);
        }

        [TestMethod]
        public void Matrix_static_Add_with_a_null_Matrix_and_a_Matrix_gives_a_copy_of_the_matrix()
        {
            var matrix = CreateMatrix(4, 4, (i, j) => (i + j) * i * j);

            var result = Matrix<double>.Add(null, matrix);

            Assert.IsInstanceOfType(result, typeof(Matrix<double>));
            Assert.AreEqual(matrix, result);
            Assert.IsFalse(ReferenceEquals(matrix, result));
        }

        [TestMethod]
        public void Matrix_static_Add_with_a_Matrix_and_a_null_Matrix_gives_a_copy_of_the_matrix()
        {
            var matrix = CreateMatrix(4, 4, (i, j) => (i + j) * i * j);

            var result = Matrix<double>.Add(matrix, (Matrix<double>)null);

            Assert.IsInstanceOfType(result, typeof(Matrix<double>));
            Assert.AreEqual(matrix, result);
            Assert.IsFalse(ReferenceEquals(matrix, result));
        }

        [TestMethod]
        public void Matrix_static_Add_with_a_Matrix_and_a_null_Computable_gives_a_copy_of_the_matrix()
        {
            var matrix = CreateMatrix(4, 4, (i, j) => (i + j) * i * j);

            var result = Matrix<double>.Add(matrix, (Computable<double>) null);

            Assert.IsInstanceOfType(result, typeof(Matrix<double>));
            Assert.AreEqual(matrix, result);
            Assert.IsFalse(ReferenceEquals(matrix, result));
        }
        #endregion

        #region Static Subtract
        [TestMethod]
        public void Matrix_static_Subtract_with_a_null_Matrix_and_a_null_Matrix_gives_null()
        {
            var result = Matrix<double>.Subtract(null, (Matrix<double>)null);

            Assert.IsNull(result);
        }

        [TestMethod]
        public void Matrix_static_Subtract_with_a_null_Matrix_and_a_null_Computable_gives_null()
        {
            var result = Matrix<double>.Subtract(null, (Computable<double>)null);

            Assert.IsNull(result);
        }

        [TestMethod]
        public void Matrix_static_Subtract_with_a_null_Matrix_and_a_Computable_gives_null()
        {
            var result = Matrix<double>.Subtract(null, 0);

            Assert.IsNull(result);
        }

        [TestMethod]
        public void Matrix_static_Subtract_with_a_null_Matrix_and_a_Matrix_gives_a_copy_of_the_negate_matrix()
        {
            var matrix = CreateMatrix(4, 4, (i, j) => (i + j) * i * j);

            var result = Matrix<double>.Subtract(null, matrix);
            matrix.Multiply(-1);

            Assert.IsInstanceOfType(result, typeof(Matrix<double>));
            Assert.AreEqual(matrix, result);
            Assert.IsFalse(ReferenceEquals(matrix, result));
        }

        [TestMethod]
        public void Matrix_static_Subtract_with_a_Matrix_and_a_null_Matrix_gives_a_copy_of_the_matrix()
        {
            var matrix = CreateMatrix(4, 4, (i, j) => (i + j) * i * j);

            var result = Matrix<double>.Subtract(matrix, (Matrix<double>)null);

            Assert.IsInstanceOfType(result, typeof(Matrix<double>));
            Assert.AreEqual(matrix, result);
            Assert.IsFalse(ReferenceEquals(matrix, result));
        }

        [TestMethod]
        public void Matrix_static_Subtract_with_a_Matrix_and_a_null_Computable_gives_a_copy_of_the_matrix()
        {
            var matrix = CreateMatrix(4, 4, (i, j) => (i + j) * i * j);

            var result = Matrix<double>.Subtract(matrix, (Computable<double>)null);

            Assert.IsInstanceOfType(result, typeof(Matrix<double>));
            Assert.AreEqual(matrix, result);
            Assert.IsFalse(ReferenceEquals(matrix, result));
        }
        #endregion

        #region Static Multiply
        [TestMethod]
        public void Matrix_static_Multiply_with_a_null_Matrix_and_a_null_Matrix_gives_null()
        {
            var result = Matrix<double>.Multiply(null, (Matrix<double>)null);

            Assert.IsNull(result);
        }

        [TestMethod]
        public void Matrix_static_Multiply_with_a_null_Matrix_and_a_null_Computable_gives_null()
        {
            var result = Matrix<double>.Multiply(null, (Computable<double>)null);

            Assert.IsNull(result);
        }

        [TestMethod]
        public void Matrix_static_Multiply_with_a_null_Matrix_and_a_Computable_gives_null()
        {
            var result = Matrix<double>.Multiply(null, 0);

            Assert.IsNull(result);
        }

        [TestMethod]
        public void Matrix_static_Multiply_with_a_null_Matrix_and_a_Matrix_gives_null()
        {
            var matrix = CreateMatrix(4, 4, (i, j) => (i + j) * i * j);

            var result = Matrix<double>.Multiply(null, matrix);
            Assert.IsNull(result);
        }

        [TestMethod]
        public void Matrix_static_Multiply_with_a_Matrix_and_a_null_Matrix_gives_a_copy_of_the_matrix()
        {
            var matrix = CreateMatrix(4, 4, (i, j) => (i + j) * i * j);

            var result = Matrix<double>.Multiply(matrix, (Matrix<double>)null);
            Assert.IsNull(result);
        }

        [TestMethod]
        public void Matrix_static_Multiply_with_a_Matrix_and_a_null_Computable_gives_the_Zero_matrix()
        {
            var matrix = CreateMatrix(4, 4, (i, j) => (i + j) * i * j);

            var result = Matrix<double>.Multiply(matrix, (Computable<double>)null);

            Assert.IsInstanceOfType(result, typeof(Matrix<double>));
            Assert.AreEqual(Matrix<double>.Zero(matrix.RowCount, matrix.ColumnCount), result);
        }
        #endregion
    }
}